package com.gxa.hualianeshop.config;

import com.gxa.hualianeshop.shiro.EmplRealm;
import com.gxa.hualianeshop.shiro.JwtFilter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author bill
 * @date 2023/7/6 15:26
 */
@Configuration
public class ShiroConfig {

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {

        //自动创建代理，没有这个鉴权可能会出错
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }


    /**
     * 去除因JSESSIONID导致第一次访问请求时报400错误
     * @return
     */
    @Bean
    public DefaultWebSessionManager mySessionManager(){
        DefaultWebSessionManager defaultSessionManager = new DefaultWebSessionManager();
        //将sessionIdUrlRewritingEnabled属性设置成false
        defaultSessionManager.setSessionIdUrlRewritingEnabled(false);
        return defaultSessionManager;
    }

    @Autowired
    private EmplRealm emplRealm;

    /**
     * 配置安全管理器的bean,使用的是EmplRealm
     * @return SecurityManager对象
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(emplRealm);
        // 让DefaultWebSessionManager生效
        securityManager.setSessionManager(mySessionManager());
        return securityManager;
    }

    /**
     * 告诉shiro, 不使用rememberme
     * 禁用session, 不保存用户登录状态。保证每次请求都重新认证。
     */
    @Bean
    protected SessionStorageEvaluator sessionStorageEvaluator(){
        DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        return sessionStorageEvaluator;
    }

    /**
     * Filter工厂，设置对应的过滤条件和跳转条件
     * 设置要放行和拦截的目标
     *
     * authc:  需要认证的角色
     * anon:  匿名,表示直接放行
     * login: 需要登录
     * logout: 登出
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {

        // 实例化shiro的过滤器工厂
        ShiroFilterFactoryBean shiroFilterFactoryBean =new ShiroFilterFactoryBean();

        // 加载安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 加载过滤器(使用的是javaee规范中的标准过滤器)
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();

        // shiro 命名的身份简写方式:
        // authc: 需要认证的身份
        // anon(匿名): 无需认证即可访问的身份

        // 用户认证的过滤流程
        filters.put("jwt",new JwtFilter());

        // 认证规则的Map
        Map<String, String> map = new HashMap<>();

        //对所有用户要求采用自定义的jwt认证
        map.put("/**", "jwt");

        // 匿名访问的接口
        map.put("/**/reg","anon");
        map.put("/**/login","anon");

        // 放行swagger3
        map.put("/swagger-ui/**","anon");
        map.put("/swagger-resources/**","anon");
        map.put("/v3/**","anon");
        // 放行doc.html  :  waggger的美化版
        map.put("/doc.html","anon");
        map.put("/webjars/**","anon");

       // 放行上传图像的访问映射地址
        map.put("/upload/**","anon");
        map.put("/cosUpload/**","anon");

        // goods模块需要SYSTEM的角色才可以访问
        // roles: 角色组,可以多个
        //map.put("/goods/**","roles[SYSTEM,SALEMAN,SAMEMANANGER]");
        //map.put("/suspension/**","roles[schoolmaster]");

        // perms: 权限分组
        //map.put("/goods/add","perms[sale:add,sale:delete]");
        //map.put("/homework/**","roles[admin]");

        // goods模块需要SYSTEM的角色才可以访问
        // roles: 角色组,可以多个

        // perms: 权限分组
        // 审批权限
        //map.put("/approve/**","perms[approve:save,approve:update]");


        // 加载认证规则
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    /**
     * 开启shiro aop注解支持.
     * 使用代理方式;所以需要开启代码支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor
    authorizationAttributeSourceAdvisor(SecurityManager  securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new  AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
